﻿/*=================================================================================================
// <copyright company="AltaModa Technologies, LLC">
//	Copyright (c) AltaModa Technologies, LLC. All rights reserved.
//	http://www.AltaModaTech.com/
// </copyright>
// 
//	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
//	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
//	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
//	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
//	CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
//	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
//	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
//	OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
//	POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================*/

using System;
using System.Web.Security;

namespace AMT.Web.Security
{
	/// <summary>
	/// Provides unrestricted membership (authentication and authorization).  This class is for development and debug purposes; DO NOT USE IN PRODUCTION!
	/// Logins always succeed; changes to passwords, password questions, etc. always succeed, but are not persisted; these behaviors can not be changed
	/// via properties.  Inherit and override to change these behaviors.
	/// </summary>
	public class PermitAllMembershipProvider : MembershipProvider
	{
		#region Private data members
		private const string _providerIdentity = "PermitAllMembershipProvider: this string is not really a password";
		private const string _providerSignal = _providerIdentity + ": this string is not really a password";
		#endregion

		public override string Description
		{
			get
			{
				return "AMT.Web.Security.Debug.PermitAllMembershipProvider - DO NOT use in production systems";
			}
		}

		#region MembershipUserCollection retrieval methods
		/// <summary>
		/// Non-functional; returns null MembershipUserCollection and 0 total records
		/// </summary>
		/// <param name="emailToMatch"></param>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <param name="totalRecords"></param>
		/// <returns>Always returns null</returns>
		public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			totalRecords = 0;
			return null;
		}

		/// <summary>
		/// Non-functional; returns null MembershipUserCollection and 0 total records
		/// </summary>
		/// <param name="usernameToMatch"></param>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <param name="totalRecords"></param>
		/// <returns></returns>
		public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
		{
			totalRecords = 0;
			return null;
		}

		/// <summary>
		/// Non-functional; returns null MembershipUserCollection and 0 total records
		/// </summary>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <param name="totalRecords"></param>
		/// <returns></returns>
		public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
		{
			totalRecords = 0;
			return null;
		}
		#endregion

		#region User password operations
		/// <summary>
		/// Unrestricted. Returns a useless string
		/// </summary>
		/// <param name="username"></param>
		/// <param name="answer"></param>
		/// <returns>A signal string that is useless as a password.</returns>
		public override string GetPassword(string username, string answer)
		{
			return _providerSignal;
		}

		/// <summary>
		/// Unrestricted. Returns a useless string
		/// </summary>
		/// <param name="username"></param>
		/// <param name="answer"></param>
		/// <returns>A signal string that is useless as a password.</returns>
		public override string ResetPassword(string username, string answer)
		{
			return _providerSignal;
		}

		/// <summary>
		/// Unrestricted. Always appears to allow password change; always returns true.
		/// NOTE: Changes are not stored or persisted.
		/// </summary>
		/// <param name="username"></param>
		/// <param name="oldPassword"></param>
		/// <param name="newPassword"></param>
		/// <returns>Always true</returns>
		public override bool ChangePassword(string username, string oldPassword, string newPassword)
		{
			return true;
		}

		/// <summary>
		/// Unrestricted. Always appears to allow password question and answer changes; always returns true.
		/// NOTE: Changes are not stored or persisted.
		/// </summary>
		/// <param name="username"></param>
		/// <param name="password"></param>
		/// <param name="newPasswordQuestion"></param>
		/// <param name="newPasswordAnswer"></param>
		/// <returns>Always true</returns>
		public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
		{
			return true;
		}

		#endregion

		#region Operations for retrieving user
		/// <summary>
		/// Creates a new MembershipUser
		/// </summary>
		/// <param name="username"></param>
		/// <param name="password"></param>
		/// <param name="email"></param>
		/// <param name="passwordQuestion"></param>
		/// <param name="passwordAnswer"></param>
		/// <param name="isApproved"></param>
		/// <param name="providerUserKey"></param>
		/// <param name="status"></param>
		/// <returns>A new, unique MembershipUser</returns>
		public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
			string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
		{
			var user = new MembershipUser(
						_providerIdentity,			// provider name
						username,					// user name
						providerUserKey,			// provider user key
						email,						// email address
						passwordQuestion,			// password question
						null,						// comment
						isApproved, false,			// is approved, is locked out
						DateTime.Now,				// creation date
						DateTime.MinValue,			// last login date
						DateTime.MinValue,			// last activity date
						DateTime.MinValue,			// last password change date
						DateTime.MinValue			// last lockout date
				);

			status = MembershipCreateStatus.Success;

			return user;
		}
		/// <summary>
		/// Always creates a new MembershipUser with the user name passed.
		/// NOTE: The MembershipUser created is not stored or persisted.
		/// </summary>
		/// <param name="username">User name for the new MembershipUser</param>
		/// <param name="userIsOnline">[unused]</param>
		/// <returns>Newly created MembershipUser</returns>
		/// <exception cref="System.ArgumentNullException">When username parameter is null</exception>
		/// <exception cref="System.ArgumentOutOfRangeException">When username parameter is an empty string</exception>
		public override MembershipUser GetUser(string username, bool userIsOnline)
		{
			// Throw exception if username is null or empty
			if (null == username) throw new ArgumentNullException("username");
			if (0 == username.Length) throw new ArgumentOutOfRangeException("username");

			MembershipCreateStatus status;
			return CreateUser(username, 
					string.Empty,			// password
					null, null, null,		// email, password question, password question answer
					true,					// is approved
					null,					// provider user key
					out status
				);
		}

		/// <summary>
		/// Always creates a new MembershipUser with the user key passed.
		/// NOTE: The MembershipUser created is not stored or persisted.
		/// </summary>
		/// <param name="providerUserKey">User key for the new MembershipUser; null allowed</param>
		/// <param name="userIsOnline">[unused]</param>
		/// <returns>Newly created MembershipUser</returns>
		public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
		{
			return new MembershipUser(
						_providerIdentity,			// provider name
						"No user name",				// user name
						providerUserKey,			// provider user key
						null, null, null,			// email, password question, comment
						true, false,				// is approved, is locked out
						DateTime.Now,				// creation date
						DateTime.MinValue,			// last login date
						DateTime.MinValue,			// last activity date
						DateTime.MinValue,			// last password change date
						DateTime.MinValue			// last lockout date
				);
		}

		/// <summary>
		/// Returns the user name portion of a valid email address; otherwise returns empty string
		/// </summary>
		/// <param name="email">A valid email address; null, empty and invalid addresses result in empty string returned.</param>
		/// <returns>The username portion from a properly formatted email address; an empty string in all other cases</returns>
		public override string GetUserNameByEmail(string email)
		{
			string retval = string.Empty;
			try
			{
				retval = new System.Net.Mail.MailAddress(email).User;
			}
			catch
			{
				// ignore all exceptions & just return empty string
			}

			return retval;
		}
		#endregion

		#region Operations on user
		/// <summary>
		/// Unrestricted. Always appears to delete user; always returns true.
		/// NOTE: Changes are not stored or persisted.
		/// </summary>
		/// <param name="username"></param>
		/// <param name="deleteAllRelatedData"></param>
		/// <returns>Always true</returns>
		public override bool DeleteUser(string username, bool deleteAllRelatedData)
		{
			return true;
		}

		/// <summary>
		/// Unrestricted. Always appears to unlock user; always returns true;
		/// </summary>
		/// <param name="userName"></param>
		/// <returns></returns>
		public override bool UnlockUser(string userName)
		{
			return true;
		}

		/// <summary>
		/// Unrestricted. All calls appear to successfully update user.
		/// </summary>
		public override void UpdateUser(MembershipUser user)
		{
			return;
		}

		/// <summary>
		/// Unrestricted. All users are validated; always returns true.
		/// </summary>
		public override bool ValidateUser(string username, string password)
		{
			return true;
		}
		#endregion

		#region Behavior and semantics controls
		/// <summary>
		/// Always enabled; always returns true
		/// </summary>
		public override bool EnablePasswordReset
		{
			get { return true; }
		}


		/// <summary>
		/// Always enabled; always returns true
		/// </summary>
		public override bool EnablePasswordRetrieval
		{
			get { return true; }
		}


		/// <summary>
		/// Effectively unlimited. Always returns int.MaxValue (~2 billion)
		/// </summary>
		public override int MaxInvalidPasswordAttempts
		{
			get { return int.MaxValue; }
		}


		/// <summary>
		/// Unrestricted. Non-alphanumeric characters are not required.
		/// </summary>
		public override int MinRequiredNonAlphanumericCharacters
		{
			get { return 0; }
		}


		/// <summary>
		/// Unrestricted. Zero length passwords are allowed.
		/// </summary>
		public override int MinRequiredPasswordLength
		{
			get { return 0; }
		}


		/// <summary>
		/// Unrestricted. Always returns 0
		/// </summary>
		/// <remarks>This property should be unused since RequiresQuestionAndAnswer returns false.</remarks>
		public override int PasswordAttemptWindow
		{
			get { return 0; }
		}


		/// <summary>
		/// Always returns Clear (plain text) format.
		/// </summary>
		public override MembershipPasswordFormat PasswordFormat
		{
			get { return MembershipPasswordFormat.Clear; }
		}


		/// <summary>
		/// Effectively unrestricted. Allows any number and kinds of characters
		/// </summary>
		public override string PasswordStrengthRegularExpression
		{
			get { return ".*"; }
		}


		/// <summary>
		/// Unrestricted. Always returns false.
		/// </summary>
		public override bool RequiresQuestionAndAnswer
		{
			get { return false; }
		}


		/// <summary>
		/// Unrestricted. Always returns false.
		/// </summary>
		public override bool RequiresUniqueEmail
		{
			get { return false; }
		}
		#endregion

		/// <summary>
		/// Retains any string set as the application name
		/// </summary>
		public override string ApplicationName { get; set; }

		/// <summary>
		/// Always returns 1 since this class has no user store or reference.
		/// </summary>
		/// <returns>Always 1</returns>
		public override int GetNumberOfUsersOnline()
		{
			return 1;
		}

		// Ensure this class is not used for production purposes
#if DEBUG
#else
#error This class is not secure and should only be used for development and debugging purposes!
#endif
	}
}
